
#ifndef FIBER_ENV_EPOLL_H_
#define FIBER_ENV_EPOLL_H_

#include <map>

#include "./native-mutex.h"
#include "./thread.h"

namespace fasmio { namespace fiber_env {

class FiberEnvImpl;
class FiberImpl;
class ThreadContext;

class Epoller
{
public:
    Epoller();
    ~Epoller();

public:
    bool Start(FiberEnvImpl *env);
    void Stop();

    // call only call from a fiber
    int WaitForReadable(int fd, const char* state);
    int WaitForWritable(int fd, const char* state);

    // make an fd to non-block
    static int MakeNonBlock(int fd);

private:
    int WaitForEvents(int fd, const char* state, unsigned int events);
    static void CompleteWait(ThreadContext*, void*);

    // epoll thread proc
    static void EpollThreadProc(void*);
    void EpollThreadProc();

    // buzz related
    bool SetupBuzz();
    void DestroyBuzz();
    bool RingBuzz();
    void ResetBuzz();

private:
    struct WaitingFiber
    {
        FiberImpl *fiber_;
        unsigned int events_;
        int error_;
    };

private:
    int epoll_fd_;
    int buzz_rd_;
    int buzz_wr_;
    bool quit_flag_;

    FiberEnvImpl *env_;

    typedef std::map<int, WaitingFiber*> waiting_fibers_t;
    NativeMutex lock_;
    waiting_fibers_t to_wait_fibers_;
    waiting_fibers_t waiting_fibers_;

    Thread epoll_thread_;
};

}}  // namespace fasmio::fiber_env

#endif  // FIBER_ENV_EPOLL_H_

